package com.sanbi.shield.server.config;

import com.sanbi.common.vo.ResponseVo;
import com.sanbi.shield.common.repsonse.CommonResponse;
import com.sanbi.shield.server.common.exceptions.BizException;
import com.sanbi.shield.server.facade.enums.ShieldExceptionMsgEnum;
import com.sanbi.shield.server.facade.enums.ShieldExceptionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 *
 * @author XiaoQingqing
 * @since 2024/06/17
 */
@Slf4j
@ResponseBody
@ControllerAdvice
public class GlobalExceptionAdvice {

    /**
     * 处理绑定异常
     *
     * @param ex 异常
     * @return 异常处理结果
     */
    @ExceptionHandler(BindException.class)
    public ResponseVo<Void> handleBindException(BindException ex){
        log.error("handle BindException", ex);
        String message = ex.getBindingResult().getAllErrors().stream()
                        .map(ObjectError::getDefaultMessage)
                        .collect(Collectors.joining());
        return ResponseVo.fail(ShieldExceptionTypeEnum.PARAM_EXCEPTION.getCode(), message);
    }

    /**
     * 处理参数异常
     *
     * @param ex 异常
     * @return 异常处理结果
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseVo<Void> handleConstraintViolationException(ConstraintViolationException ex){
        log.error("handle ConstraintViolationException", ex);
        return ResponseVo.fail(ShieldExceptionTypeEnum.PARAM_EXCEPTION.getCode(), ex.getMessage());
    }

    /**
     * 处理请求体异常
     *
     * @param ex 异常
     * @return 异常处理结果
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseVo<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex){
        log.error("handle MethodArgumentNotValidException", ex);
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder(",");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append(": ").append(fieldError.getDefaultMessage()).append(",");
        }
        return ResponseVo.fail(ShieldExceptionTypeEnum.PARAM_EXCEPTION.getCode(), sb.substring(1));
    }

    /**
     * 处理请求体异常
     *
     * @param ex 异常
     * @return 异常处理结果
     */
    @ExceptionHandler(BizException.class)
    public ResponseVo<Void> handleParamException(BizException ex){
        log.error("handle BizException", ex);
        ShieldExceptionMsgEnum msgEnum = ex.getMassageEnum();
        return ResponseVo.fail(msgEnum.getCode(), ex.getMessage());
    }

    /**
     * 处理未知异常
     *
     * @param ex 异常
     * @return 异常处理结果
     */
    @ExceptionHandler(Exception.class)
    public ResponseVo<Void> handleException(Exception ex){
        log.error("handle Exception", ex);
        return ResponseVo.fail(ShieldExceptionTypeEnum.UNKNOWN_EXCEPTION.getCode(), ShieldExceptionTypeEnum.UNKNOWN_EXCEPTION.getName());
    }

}
